package org.piaohao.util.file;

import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import com.jfinal.kit.FileKit;
import com.jfinal.kit.PathKit;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created on : 2013-5-7, 17:57:25
 *
 * @author piaohao
 */
public class FileUtil {

    private static final int WORD_HTML = 8;
    private static final int WORD_TXT = 7;
    private static final int EXCEL_HTML = 44;
    private static String OpenOffice_HOME = "c:\\Program Files\\OpenOffice.org 3\\";//这里是OpenOffice的安装目录, 在我的项目中,为了便于拓展接口,没有直接写成这个样子,但是这样是绝对没问题的  
    //启动OpenOffice的服务  
//    private static String command = OpenOffice_HOME
//            + "program\\soffice.exe -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\"";
    private final static String command = "C:\\OpenOffice\\program\\soffice.exe -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\"";
    private static Process pro = null;
    // connect to an OpenOffice.org instance running on port 8100  
    private static OpenOfficeConnection connection = null;
    // convert  
    private static DocumentConverter converter = null;

//    static {
//        try {
//            pro = Runtime.getRuntime().exec(command);
//        } catch (ConnectException ex) {
//            Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, null, ex);
//        } catch (IOException ex) {
//            Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, null, ex);
//        }
//    }
    /**
     * WORD转HTML
     *
     * @param docfile WORD文件全路径
     * @param htmlfile 转换后HTML存放路径
     */
    public static void wordToHtml(String docfile, String htmlfile) {
        ActiveXComponent app = new ActiveXComponent("Word.Application"); // 启动word  
        try {
            app.setProperty("Visible", new Variant(false));
            Dispatch docs = app.getProperty("Documents").toDispatch();
            Dispatch doc = Dispatch.invoke(
                    docs,
                    "Open",
                    Dispatch.Method,
                    new Object[]{docfile, new Variant(false),
                new Variant(true)}, new int[1]).toDispatch();
            Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[]{
                htmlfile, new Variant(WORD_HTML)}, new int[1]);
            Variant f = new Variant(false);
            Dispatch.call(doc, "Close", f);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            app.invoke("Quit", new Variant[]{});
        }
    }

    /**
     * EXCEL转HTML
     *
     * @param xlsfile EXCEL文件全路径
     * @param htmlfile 转换后HTML存放路径
     */
    public static void excelToHtml(String xlsfile, String htmlfile) {
        ActiveXComponent app = new ActiveXComponent("Excel.Application"); // 启动excel  
        try {
            app.setProperty("Visible", new Variant(false));
            Dispatch excels = app.getProperty("Workbooks").toDispatch();
            Dispatch excel = Dispatch.invoke(
                    excels,
                    "Open",
                    Dispatch.Method,
                    new Object[]{xlsfile, new Variant(false),
                new Variant(true)}, new int[1]).toDispatch();
            Dispatch.invoke(excel, "SaveAs", Dispatch.Method, new Object[]{
                htmlfile, new Variant(EXCEL_HTML)}, new int[1]);
            Variant f = new Variant(false);
            Dispatch.call(excel, "Close", f);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            app.invoke("Quit", new Variant[]{});
        }
    }

    /**
     * 将word文档转换成html文档
     *
     * @param docFile 需要转换的word文档
     * @param filepath 转换之后html的存放路径
     * @return 转换之后的html文件
     */
    public static File convert(File docFile, String filepath) {

        // 创建保存html的文件  
        File htmlFile = new File(filepath + "/" + new Date().getTime() + ".html");
        // 创建Openoffice连接  
        OpenOfficeConnection con = new SocketOpenOfficeConnection(8100);
        try {
            // 连接  
            con.connect();
        } catch (ConnectException e) {
            System.out.println("获取OpenOffice连接失败...");
            e.printStackTrace();
        }

        // 创建转换器  
        DocumentConverter converter = new OpenOfficeDocumentConverter(con);
        // 转换文档问html  
        converter.convert(docFile, htmlFile);
        // 关闭openoffice连接  
        con.disconnect();
        return htmlFile;
    }

    /**
     *
     * 将word转换成html文件，并且获取html文件代码。
     *
     * @param docFile 需要转换的文档
     * @param filepath 文档中图片的保存位置
     * @return 转换成功的html代码
     */
    public static String toHtmlString(File docFile, String filepath) {
        // 转换word文档  
        File htmlFile = convert(docFile, filepath);

        /*try { 
         FileUtils.copyFile(docFile,new File("e://ee.doc")); 
         FileInputStream input = FileUtils.openInputStream(docFile); 
         FileOutputStream output = new FileOutputStream(new File("e://ff.doc")); 
         IOUtils.copyLarge(input, output); 
         
         } catch (IOException e1) { 
         e1.printStackTrace(); 
         }*/
        // 获取html文件流  
        StringBuffer htmlSb = new StringBuffer();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(htmlFile), Charset.forName("gb2312")));
            while (br.ready()) {
                htmlSb.append(br.readLine());
            }
            br.close();
            // 删除临时文件  
            htmlFile.delete();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // HTML文件字符串  
        String htmlStr = htmlSb.toString();
        System.out.println("htmlStr=" + htmlStr);
        // 返回经过清洁的html文本  
        return clearFormat(htmlStr, filepath);
    }

    /**
     *
     * 清除一些不需要的html标记
     *
     *
     *
     * @param htmlStr
     *
     * 带有复杂html标记的html语句
     *
     * @return 去除了不需要html标记的语句
     */
    protected static String clearFormat(String htmlStr, String docImgPath) {

        // 获取body内容的正则  
        String bodyReg = "<BODY .*</BODY>";
        Pattern bodyPattern = Pattern.compile(bodyReg);
        Matcher bodyMatcher = bodyPattern.matcher(htmlStr);
        if (bodyMatcher.find()) {
            // 获取BODY内容，并转化BODY标签为DIV  
            htmlStr = bodyMatcher.group().replaceFirst("<BODY", "<DIV").replaceAll("</BODY>", "</DIV>");
        }

        // 调整图片地址  
        htmlStr = htmlStr.replaceAll("<IMG SRC=\"", "<IMG SRC=\"" + docImgPath + "/");
        // 把<P></P>转换成</div></div>保留样式  
        // content = content.replaceAll("(<P)([^>]*>.*?)(<\\/P>)",  
        // "<div$2</div>");  
        // 把<P></P>转换成</div></div>并删除样式  
        htmlStr = htmlStr.replaceAll("(<P)([^>]*)(>.*?)(<\\/P>)", "<p$3</p>");
        // 删除不需要的标签  
        htmlStr = htmlStr.replaceAll("<[/]?(font|FONT|span|SPAN|xml|XML|del|DEL|ins|INS|meta|META|[ovwxpOVWXP]:\\w+)[^>]*?>", "");
        // 删除不需要的属性  
        htmlStr = htmlStr.replaceAll("<([^>]*)(?:lang|LANG|class|CLASS|style|STYLE|size|SIZE|face|FACE|[ovwxpOVWXP]:\\w+)=(?:'[^']*'|\"\"[^\"\"]*\"\"|[^>]+)([^>]*)>", "<$1$2>");

        return htmlStr;

    }

    /**
     * 将Office文档转换为PDF. 运行该函数需要用到OpenOffice, OpenOffice下载地址为
     * http://www.openoffice.org/
     *
     * <pre>
     * 方法示例:
     * String sourcePath = "F:\\office\\source.doc";
     * String destFile = "F:\\pdf\\dest.pdf";
     * Converter.office2PDF(sourcePath, destFile);
     * </pre>
     *
     * @param sourceFile 源文件, 绝对路径. 可以是Office2003-2007全部格式的文档, Office2010的没测试.
     * 包括.doc, .docx, .xls, .xlsx, .ppt, .pptx等. 示例: F:\\office\\source.doc
     * @param destFile 目标文件. 绝对路径. 示例: F:\\pdf\\dest.pdf
     * @return 操作成功与否的提示信息. 如果返回 -1, 表示找不到源文件, 或url.properties配置错误; 如果返回 0,
     * 则表示操作成功; 返回1, 则表示转换失败
     */
    public static int office2PDF(String sourceFile, String destFile) {
        File inputFile = new File(sourceFile);
        if (!inputFile.exists()) {
            return -1;// 找不到源文件, 则返回-1  
        }
        connection = new SocketOpenOfficeConnection("127.0.0.1", 8100);
        try {
            connection.connect();
        } catch (ConnectException ex) {
            Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, null, ex);
        }
        converter = new OpenOfficeDocumentConverter(connection);

        // 如果目标路径不存在, 则新建该路径  
        File outputFile = new File(destFile);
        if (!outputFile.getParentFile().exists()) {
            outputFile.getParentFile().mkdirs();
        }

        converter.convert(inputFile, outputFile);
        connection.disconnect();
        return 0;
    }

    public static void release() {
        if (connection != null) {
            connection.disconnect();
        }
        if (pro != null) {
            pro.destroy();
        }
    }

    /**
     * 转换
     *
     * @param pdfPath
     * @param swfPath
     * @return
     * @version V3.1
     */
    public static boolean convertPDF2SWF(String pdfPath, String swfPath) {
        try {
            String exePath = "C:\\SWFTools\\pdf2swf.exe";
            String command = exePath + "  -t \"" + pdfPath + "\" -o  \"" + swfPath
                    + "\" -s flashversion=9 -s languagedir=D:\\360云盘\\编程相关\\swf_language\\usr\\share\\xpdf\\chinese-simplified";

            Process process = Runtime.getRuntime().exec(command); // 调用外部程序   
            final InputStream is1 = process.getInputStream();
            new Thread(new Runnable() {
                public void run() {
                    BufferedReader br = new BufferedReader(new InputStreamReader(is1));
                    try {
                        while (br.readLine() != null) ;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start(); // 启动单独的线程来清空process.getInputStream()的缓冲区   
            InputStream is2 = process.getErrorStream();
            BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
            StringBuilder buf = new StringBuilder(); // 保存输出结果流   
            String line = null;
            while ((line = br2.readLine()) != null) {
                buf.append(line); // 循环等待ffmpeg进程结束   
            }			//System.out.println("输出结果为：" + buf);
            while (br2.readLine() != null) {
            };
            process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static void office2swf(String srcFile, String outputPath) {
        String parentPath = outputPath.substring(0, outputPath.indexOf("\\"));
        String tmpPdf = parentPath + "\\" + System.currentTimeMillis() + ".pdf";
        office2PDF(srcFile, tmpPdf);
        convertPDF2SWF(tmpPdf, outputPath);
        FileKit.delete(new File(tmpPdf));
    }

    /*
     * 删除文件夹
     * @param folderPath 文件夹完整绝对路径
     */
    public static boolean delFolder(String folderPath) {
        try {
            java.io.File myFile = new java.io.File(folderPath);
            if (myFile.exists()) {
                return myFile.delete(); //删除空文件夹
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除指定文件夹下所有文件
     *
     * @param path 文件夹完整绝对路径
     */
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);//再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }

    /**
     *
     * 复制文件或文件夹
     *
     * @param srcPath 源文件或源文件夹的路径
     *
     * @param destDir 目标文件所在的目录
     *
     * @return
     *
     */
    public static boolean copyGeneralFile(String srcPath, String destDir) {
        boolean flag = false;
        File file = new File(srcPath);
        if (!file.exists()) {    // 源文件或源文件夹不存在
            return false;
        }
        if (file.isFile()) {    // 文件复制
            flag = copyFile(srcPath, destDir);
        } else if (file.isDirectory()) {   // 文件夹复制
            flag = copyDirectory(srcPath, destDir);
        }
        return flag;

    }

    /**
     *
     * 默认的复制文件方法，默认会覆盖目标文件夹下的同名文件
     *
     * @param srcPath
     *
     * 源文件绝对路径
     *
     * @param destDir
     *
     * 目标文件所在目录
     *
     * @return boolean
     *
     */
    public static boolean copyFile(String srcPath, String destDir) {
        return copyFile(srcPath, destDir, true); // 默认覆盖同名文件
    }

    /**
     *
     * 默认的复制文件夹方法，默认会覆盖目标文件夹下的同名文件夹
     *
     * @param srcPath 源文件夹路径
     *
     * @param destPath 目标文件夹所在目录
     *
     * @return boolean
     *
     */
    public static boolean copyDirectory(String srcPath, String destDir) {
        return copyDirectory(srcPath, destDir, true);
    }

    /**
     *
     * 复制文件到目标目录
     *
     * @param srcPath
     *
     * 源文件绝对路径
     *
     * @param destDir
     *
     * 目标文件所在目录
     *
     * @param overwriteExistFile
     *
     * 是否覆盖目标目录下的同名文件
     *
     * @return boolean
     *
     */
    public static boolean copyFile(String srcPath, String destDir, boolean overwriteExistFile) {
        boolean flag = false;
        File srcFile = new File(srcPath);
        if (!srcFile.exists() || !srcFile.isFile()) { // 源文件不存在
            return false;
        }
        //获取待复制文件的文件名
        String fileName = srcFile.getName();
        String destPath = destDir + File.separator + fileName;
        File destFile = new File(destPath);
        if (destFile.getAbsolutePath().equals(srcFile.getAbsolutePath())) { // 源文件路径和目标文件路径重复
            return false;
        }

        if (destFile.exists() && !overwriteExistFile) {    // 目标目录下已有同名文件且不允许覆盖
            return false;
        }

        File destFileDir = new File(destDir);
        if (!destFileDir.exists() && !destFileDir.mkdirs()) {    // 目录不存在并且创建目录失败直接返回
            return false;
        }
        try {
            FileInputStream fis = new FileInputStream(srcPath);
            FileOutputStream fos = new FileOutputStream(destFile);
            byte[] buf = new byte[1024];
            int c;
            while ((c = fis.read(buf)) != -1) {
                fos.write(buf, 0, c);
            }
            fos.flush();
            fis.close();
            fos.close();
            flag = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * @param srcPath 源文件夹路径
     *
     * @param destPath 目标文件夹所在目录
     *
     * @return
     *
     */
    public static boolean copyDirectory(String srcPath, String destDir, boolean overwriteExistDir) {
        if (destDir.contains(srcPath)) {
            return false;
        }
        boolean flag = false;
        File srcFile = new File(srcPath);
        if (!srcFile.exists() || !srcFile.isDirectory()) { // 源文件夹不存在
            return false;
        }
        //获得待复制的文件夹的名字，比如待复制的文件夹为"E:\\dir\\"则获取的名字为"dir"
        String dirName = srcFile.getName();
        //目标文件夹的完整路径

        String destDirPath = destDir + File.separator + dirName + File.separator;
        File destDirFile = new File(destDirPath);
        if (destDirFile.getAbsolutePath().equals(srcFile.getAbsolutePath())) {
            return false;
        }
        if (destDirFile.exists() && destDirFile.isDirectory() && !overwriteExistDir) {    // 目标位置有一个同名文件夹且不允许覆盖同名文件夹，则直接返回false
            return false;
        }

        if (!destDirFile.exists() && !destDirFile.mkdirs()) {  // 如果目标目录不存在并且创建目录失败
            return false;
        }

        File[] fileList = srcFile.listFiles();    //获取源文件夹下的子文件和子文件夹
        if (fileList.length == 0) {    // 如果源文件夹为空目录则直接设置flag为true，这一步非常隐蔽，debug了很久
            flag = true;
        } else {
            for (File temp : fileList) {
                if (temp.isFile()) {    // 文件
                    flag = copyFile(temp.getAbsolutePath(), destDirPath, overwriteExistDir);        // 递归复制时也继承覆盖属性
                } else if (temp.isDirectory()) {    // 文件夹
                    flag = copyDirectory(temp.getAbsolutePath(), destDirPath, overwriteExistDir);   // 递归复制时也继承覆盖属性
                }

                if (!flag) {
                    break;
                }
            }
        }
        return flag;
    }

    /**
     *
     * 由上面方法延伸出剪切方法：复制+删除
     *
     * @param destDir 同上
     *
     */
    public static boolean cutGeneralFile(String srcPath, String destDir) {
        boolean flag = false;
        if (copyGeneralFile(srcPath, destDir) && delFolder(srcPath)) { // 复制和删除都成功
            flag = true;
        }
        return flag;
    }

    public static void main(String[] args) {
        //        for (int i = 0; i < 20; i++) {
        //            FileUtil.office2PDF("C:\\Users\\Administrator\\Desktop\\重庆理工大学2013届毕业合影拍摄方案.doc",
        //                    "C:\\Users\\Administrator\\Desktop\\test" + i + ".pdf");
        //        }
        //        FileUtil.release();
        //        FileUtil.convertPDF2SWF("C:\\Users\\Administrator\\Desktop\\重庆理工大学2013届毕业合影拍摄方案.pdf",
        //                "C:\\Users\\Administrator\\Desktop\\重庆理工大学2013届毕业合影拍摄方案.swf");
        long start = System.currentTimeMillis();
        FileUtil.delAllFile("D:\\360云盘\\编程相关\\开源项目\\jfinal1.4\\JFinal-src-1.4");
        System.out.println((System.currentTimeMillis() - start) / 1000 + "s");
    }
}
